package com.wh.wisdomsite.xbox.core.event;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created with IntelliJ IDEA.
 * User: yl
 * Date: 13-2-22
 * Time: 上午11:41
 * To change this template use File | Settings | File Templates.
 */
public abstract class AbstractXboxEventMulticaster implements XboxEventMulticaster {


    private Set<XboxEventListener> xboxEventListeners = new HashSet<XboxEventListener>();


    private static final Map<Class<? extends XboxEvent>, ListenerRegistry> EVENT_LISTENER_MAPPING = new ConcurrentHashMap<Class<? extends XboxEvent>, ListenerRegistry>();

    /**
     * 增加一个监听器
     * @param listener
     */
    @Override
    public void addListener(XboxEventListener listener) {
        xboxEventListeners.add(listener);
    }

    /**
     * 增加一组监听器
     * @param list
     */
    @Override
    public void addListener(List<XboxEventListener> list) {
        xboxEventListeners.addAll(list);
    }

    /**
     * 删除某个监听器
     * @param listener
     */
    @Override
    public void removeListener(XboxEventListener listener) {
        xboxEventListeners.remove(listener);
    }

    /**
     * 删除所有监听器
     */
    @Override
    public void removeAllListener() {
        xboxEventListeners.clear();
    }

    /**
     * 根据事件类型获取对应的监听器
     * @param event
     * @return
     */
    protected List<XboxEventListener> getXboxEventListeners(XboxEvent event) {
        Class<? extends XboxEvent> eventType = event.getClass();
        if (!EVENT_LISTENER_MAPPING.containsKey(eventType)) {
            List<XboxEventListener> listeners = new ArrayList<XboxEventListener>();
            if (xboxEventListeners != null && xboxEventListeners.size() > 0) {
                for (XboxEventListener xboxEventListener : xboxEventListeners) {
                    if (supportsEvent(xboxEventListener, eventType)) {
                        listeners.add(xboxEventListener);
                    }
                }
                sortXboxEventListeners(listeners);
            }
            ListenerRegistry listenerRegistry = new ListenerRegistry(listeners);
            EVENT_LISTENER_MAPPING.put(eventType, listenerRegistry);
        }

        return EVENT_LISTENER_MAPPING.get(eventType).getXboxEventListeners();
    }

    /**
     * 判断是否支持事件类型
     * @param listener
     * @param eventType
     * @return
     */
    protected boolean supportsEvent(XboxEventListener listener, Class<? extends XboxEvent> eventType) {
        SmartXboxEventListener smartXboxEventListener = (listener instanceof SmartXboxEventListener)
                ? (SmartXboxEventListener) listener : new GenericXboxEventAdapter(listener);
        return smartXboxEventListener.supportsEventType(eventType);
    }

    protected void sortXboxEventListeners(List<XboxEventListener> listeners) {
        Collections.sort(listeners, new Comparator<XboxEventListener>() {
            @Override
            public int compare(XboxEventListener o1, XboxEventListener o2) {
                if (o1.getOrder() > o2.getOrder()) {
                    return 1;
                } else if (o1.getOrder() < o2.getOrder()) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
    }


    private class ListenerRegistry {
        private List<XboxEventListener> xboxEventListeners;

        private ListenerRegistry(List<XboxEventListener> xboxEventListeners) {
            this.xboxEventListeners = xboxEventListeners;
        }

        public List<XboxEventListener> getXboxEventListeners() {
            return xboxEventListeners;
        }
    }
}
